package servlet;

import it.polimi.swimv2.exception.LoginManagerException;
import it.polimi.swimv2.remote.LoginManagerRemote;
import it.polimi.swimv2.session.UserRole;
import it.polimi.swimv2.util.RemoteBindingName;

import java.io.IOException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet implementation class LoginServlet
 */
public class LoginServlet extends HttpServlet {
	
	//Jsp pages
	private static final String ERROR_JSP = "error.jsp";
	private static final String INDEX_JSP = "index.jsp";
	private static final String LOGIN_FORM_JSP = "loginForm.jsp";
	
	//Parameters for http request
	private static final String LOGIN = "login";
	private static final String ADMIN = "admin";	
	private static final String PASSWORD = "password";
	private static final String USERNAME = "username";	
	private static final String USER = "user";
	private static final String LOGOUT = "logout";	
	private static final String ACT = "act";
	private static final String LOGIN_FORM = "loginForm";	
	
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public LoginServlet() {
		super();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		redirectLog(request, response);
	}
	
	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		redirectLog(request, response);
	}
	
	/**
	 * manages the action requested by http request
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException 
	 */
	private void redirectLog(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		String act = request.getParameter(ACT);
		if (act == null) {
			response.sendRedirect(ERROR_JSP);
			return;
		}

		if (act.equals(LOGIN_FORM)) {
			showLoginForm(request, response);
		} else if (act.equals(LOGOUT)) {
			processLogout(request, response);
		} else if (act.equals(LOGIN)){
			login(request, response);
		}else {
			response.sendRedirect(ERROR_JSP);
		}
	}
	/**
	 * manages the logout
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	private void processLogout(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		HttpSession session = request.getSession();
		if (session.getAttribute(USER) != null) {
			session.setAttribute(USER, null);

		} else if (session.getAttribute(ADMIN) != null) {
			session.setAttribute(ADMIN, null);
		}
		response.sendRedirect(INDEX_JSP);
	}
	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	private void showLoginForm(HttpServletRequest request,
			HttpServletResponse response) throws IOException {

		HttpSession session = request.getSession();
		if (needToStartNew(session) == true) {
			response.sendRedirect(LOGIN_FORM_JSP);
		} else {
			response.sendRedirect(INDEX_JSP);
		}
	}

	private boolean needToStartNew(HttpSession session) {
		return (session.isNew() || session.getAttribute(USER) == null || session
				.getAttribute(ADMIN) == null);
	}

	/**
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	private void login(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		String username = request.getParameter(USERNAME);
		String password = request.getParameter(PASSWORD);

		try {
			LoginManagerRemote rem = retrieveLoginManagerRemote();
			UserRole userRole = rem.authenticate(username, password);
			sendResponse(request, response, username, userRole);
		} catch (NamingException e) {
			response.sendRedirect(ERROR_JSP);
		} catch (LoginManagerException e) {
			request.setAttribute("loginError", "error");
			RequestDispatcher dispatcher = request
					.getRequestDispatcher(LOGIN_FORM_JSP);
			dispatcher.forward(request, response);
		}

	}

	/**
	 * 
	 * @param request
	 * @param response
	 * @param username
	 * @param userRole
	 *            : shows if the user logged in is the administrator or a
	 *            registered user.
	 * @throws IOException
	 */
	private void sendResponse(HttpServletRequest request,
			HttpServletResponse response, String username, UserRole userRole)
			throws IOException {

		HttpSession session = request.getSession();
		switch (userRole) {
		case User:
			session.setAttribute(USER, username);
			break;
		case Admin:
			session.setAttribute(ADMIN, username);
		}
		response.sendRedirect(INDEX_JSP);
	}

	/**
	 * Manages the jndi connection.
	 * 
	 * @return
	 * @throws NamingException
	 */
	private LoginManagerRemote retrieveLoginManagerRemote()
			throws NamingException {
		Context jndiContext = new InitialContext();
		Object ref = jndiContext.lookup(RemoteBindingName.LOGIN_MANAGER);
		return (LoginManagerRemote) ref;
	}

}
